using Component;
using System.Net;
using System.Text;
using MainServer;


namespace Entity
{
    public delegate void EntityEvent(IEntity entity);
    public interface IEntity
    {
        public event EntityEvent OnEntityCreated;
        public event EntityEvent OnEntityReleased;
        public event EntityEvent OnComponentAdded;
        public event EntityEvent OnComponentRemoved;
        public event EntityEvent OnComponentReplaced;
        int Id { get; }
        List<IComponent> Components { get; }
        HashSet<Type> ComponentTypes { get; }
        bool IsActive { get; set; }
        public void Release() { }
        public void AddComponent(IComponent component) { }
        public void RemoveComponent(IComponent component) { }
        public void ReplaceComponent(IComponent oldComponent, IComponent newComponent) { }
    }
    public class Entity : IEntity
    {
        public event EntityEvent OnEntityCreated = (entity) => { };
        public event EntityEvent OnEntityReleased = (entity) => { };
        public event EntityEvent OnComponentAdded = (entity) => { };
        public event EntityEvent OnComponentRemoved = (entity) => { };
        public event EntityEvent OnComponentReplaced = (entity) => { };
        public int Id { get; }
        public List<IComponent> Components { get; }
        public HashSet<Type> ComponentTypes { get; }
        public bool IsActive { get; set; }
        public Entity(int _Id)
        {
            Id = _Id;
            Components = [];
            ComponentTypes = [];
            OnEntityCreated?.Invoke(this);
        }
        public void Release()
        {
            OnEntityReleased?.Invoke(this);
        }
        /// <summary>
        /// 将该组件添加到Entity
        /// </summary>
        /// <param name="component">要添加的组件</param>
        public void AddComponent(IComponent component)
        {
            Components.Add(component);
            ComponentTypes.Add(component.GetType());
            OnComponentAdded?.Invoke(this);
        }
        /// <summary>
        /// 将该类型的组件新建并添加到Entity
        /// </summary>
        /// <param name="componentType">组件类型</param>
        /// <exception cref="ComponentTypeNotFoundException">若该类型的组件不存在，则报错</exception>
        public void AddComponent(Type componentType)
        {
            Components.Add((IComponent?)Activator.CreateInstance(componentType, 1)
                            ?? throw new ComponentTypeNotFoundException(componentType));
            //此处报错大概率不会触发，但为解决null值故设置
            ComponentTypes.Add(componentType);
            //此处若能执行则说明已经成功创建到Components中，故也可以添加到ComponentTypes
            OnComponentAdded?.Invoke(this);
        }
        /// <summary>
        /// 移除所有该类型的组件
        /// </summary>
        /// <param name="componentType">组件类型</param>
        /// <exception cref="ComponentNotExistException">若Entity中不存在该类型的组件，则报错</exception>
        public void RemoveComponent(Type componentType)
        {
            if (Components.RemoveAll(c => c.GetType() == componentType) == 0) //若不存在
            //TODO: 可能的性能优化
            {
                throw new ComponentNotExistException(componentType, this);
                //若该Entity中不包含该Component，则报错
            }
            ComponentTypes.Remove(componentType);
            OnComponentRemoved?.Invoke(this); //若删除成功则执行
        }
        /// <summary>
        /// 移除该组件
        /// </summary>
        /// <param name="component">要移除的组件本身</param>
        /// <exception cref="ComponentNotExistException">若Entity不存在该组件，则报错</exception>
        public void RemoveComponent(IComponent component)
        {
            if (Components.RemoveAll(c => c.Equals(component)) == 0)
            {
                throw new ComponentNotExistException(component, this);
                //若该Entity中不包含该Component，则报错
            }
            ComponentTypes.Remove(component.GetType());
            OnComponentRemoved?.Invoke(this); //若删除成功则执行
        }
        /// <summary>
        /// 移除该Index下的组件
        /// </summary>
        /// <param name="componentIndex">组件Index</param>
        /// <exception cref="ComponentNotExistException">若Index超出范围，则报错</exception>
        public void RemoveComponent(int componentIndex)
        {
            if (componentIndex >= Components.Count() - 1 || componentIndex < 0)
            {
                throw new ComponentNotExistException(componentIndex, this);
                //不存在组件直接报错返回
            }
            Components.RemoveAt(componentIndex);
            OnComponentRemoved?.Invoke(this); //若删除成功则执行
        }
        /// <summary>
        /// 替换old组件为new组件
        /// </summary>
        /// <param name="oldComponent">要替换的组件</param>
        /// <param name="newComponent">新的组件</param>
        /// <exception cref="ComponentNotExistException">若要替换的组件不存在，则报错</exception>
        public void ReplaceComponent(IComponent oldComponent, IComponent newComponent)
        {
            int _index = Components.FindIndex(c => c.Equals(oldComponent));
            if (_index == -1)
            {
                throw new ComponentNotExistException(oldComponent, this);
                //不存在组件直接报错返回
            }
            Components[_index] = newComponent;
            OnComponentReplaced?.Invoke(this);
        }
        /// <summary>
        /// 替换第一个old类型的组件为new组件
        /// </summary>
        /// <param name="oldComponent">要替换的组件类型</param>
        /// <param name="newComponent">新的组件</param>
        /// <exception cref="ComponentNotExistException">若要替换的组件类型不存在于Entity，则报错</exception>
        public void ReplaceComponent(Type oldComponentType, IComponent newComponent)
        {
            int _index = Components.FindIndex(c => c.GetType() == oldComponentType);
            if (_index == -1)
            {
                throw new ComponentNotExistException(oldComponentType, this);
                //不存在组件直接报错返回
            }
            Components[_index] = newComponent;
            OnComponentReplaced?.Invoke(this);
        }
        /// <summary>
        /// 将该Index下的组件替换为new组件
        /// </summary>
        /// <param name="oldComponentIndex">要替换的位置(0->)</param>
        /// <param name="newComponent">新的组件</param>
        /// <exception cref="ComponentNotExistException">若Index超出范围，则报错</exception>
        public void ReplaceComponent(int oldComponentIndex, IComponent newComponent)
        {
            if (oldComponentIndex >= Components.Count - 1 || oldComponentIndex < 0)
            {
                throw new ComponentNotExistException(oldComponentIndex, this);
                //不存在组件直接报错返回
            }
            Components[oldComponentIndex] = newComponent;
            OnComponentReplaced?.Invoke(this);
        }

    }
    public class Player
    {
        private long uid;
        private string account = string.Empty;
        private string password = string.Empty;
        private IPEndPoint addr = new(IPAddress.Parse("1.1.1.1"), 1);
        private long character_id;
        private string character_name = string.Empty;
        private string status = string.Empty;
        private double hp_max;
        private double hp;
        private double mp_max;
        private double mp;
        private double atk;
        private double def;
        private double crit;
        private double crit_damage;
        private double dex; //精确度
        private double pot; //潜力
        private long lv;
        private double exp;
        private double exp_max;
        private int[] position = new int[2];
        private string dimension = string.Empty;
        public long UID { get { return uid; } set { uid = value; } }
        public string Account { get { return account; } set { account = value; } }
        public string Password { get { return password; } set { password = value; } }
        public IPEndPoint Addr { get { return addr; } set { addr = value; } }
        public long CharacterId { get { return character_id; } set { character_id = value; } }
        public string CharacterName { get { return character_name; } set { character_name = value; } }
        public string Status { get { return status; } set { status = value; } }
        public double HpMax
        {
            get { return hp_max; }
            set
            {
                hp_max = value;
                byte[] buffer = Encoding.UTF8.GetBytes($@"210|{hp_max}"); //（指令-当前生命最大值）
                Server.udpClient.Send(buffer, addr);
            }
        }
        public double Hp
        {
            get { return hp; }
            set
            {
                hp = value;
                byte[] buffer = Encoding.UTF8.GetBytes($@"209|{hp}"); //(指令-当前生命值)
                Server.udpClient.Send(buffer, addr);
            }
        }
        public double MpMax
        {
            get { return mp_max; }
            set
            {
                mp_max = value;
                byte[] buffer = Encoding.UTF8.GetBytes($@"212|{mp_max}"); //(指令-当前内力最大值)
                Server.udpClient.Send(buffer, addr);
            }
        }
        public double Mp
        {
            get { return mp; }
            set
            {
                mp = value;
                byte[] buffer = Encoding.UTF8.GetBytes($@"211|{mp}"); //(指令-当前内力值)
                Server.udpClient.Send(buffer, addr);
            }
        }
        public double Atk { get { return atk; } set { atk = value; } }
        public double Def { get { return def; } set { def = value; } }
        public double Crit { get { return crit; } set { crit = value; } }
        public double CritDam { get { return crit_damage; } set { crit_damage = value; } }
        public double Dex { get { return dex; } set { dex = value; } }
        public double Pot { get { return pot; } set { pot = value; } }
        public long Lv { get { return lv; } set { lv = value; } }
        public double Exp { get { return exp; } set { exp = value; } }
        public double ExpMax { get { return exp_max; } set { exp_max = value; } }
        public int[] Position { get { return position; } set { position = value; } }
        public string Dimension { get { return dimension; } set { dimension = value; } }
        public Player(
            IPEndPoint addr_,
            string status_,
            long? uid_ = null,
            string? account_ = null,
            string? password_ = null,
            long? character_id_ = null,
            string? character_name_ = null
            )
        {
            UID = uid_ ?? 0;
            Account = account_ ?? string.Empty;
            Password = password_ ?? string.Empty;
            Addr = addr_;
            CharacterId = character_id_ ?? 0;
            CharacterName = character_name_ ?? string.Empty;
            Status = status_ ?? string.Empty;
            Dimension = Server.settings["default_dimension"];
            Position = [int.Parse(Server.settings["default_y"]), int.Parse(Server.settings["default_x"])];
        }
        /// <summary>
        /// 将除了addr以外的全部player属性重置（清空）
        /// </summary>
        public void ResetPlayer()
        {
            Account = string.Empty;
            UID = 0;
            Password = string.Empty;
            CharacterId = 0;
            CharacterName = string.Empty;
            Status = string.Empty;
        }
        /// <summary>
        /// 以字符串形式打包返回该玩家的所有状态
        /// </summary>
        /// <returns>内容为：""hp":...,"hp_max":...,..."</returns> 
        public string GetAllAttributesString()
        {
            string attributes = string.Empty;
            attributes += @$"""hp"":{hp},""hp_max"":{hp_max},""mp"":{mp},""mp_max"":{mp_max},""atk"":{atk},""def"":{def},""crit"":{crit},""crit_damage"":{crit_damage},""dex"":{dex},""pot"":{pot},""lv"":{lv},""exp"":{exp},""exp_max"":{exp_max}";
            return attributes;

        }
        ~Player()
        {
            Server.logger.Info($"玩家{UID}[{Account}]退出了游戏");
        }
    }
}